package com.example.NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * 1. Scattering 将数据写入到 buffer时，可以采用 buffer 数组，依次写入 【分散】
 * 2. gathering 从 buffer 读取数据时，可以采用 buffer 数组，依次读写【采集】
 *
 * 当一个 buffer 数组中的不够时，可以用数组来扩展
 * 可以使用 telnet 来测试该段代码
 */
public class ScatteringAndGathering {
    public static void main(String[] args) throws IOException {
        // 使用 ServerSocketChannel 和 SocketChannel 网络

        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);
        // 绑定端口到 socket 并启动
        socketChannel.socket().bind(inetSocketAddress);

        // 创建 bufer 数组
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(3);

        // 等待客户端连接（telnet）
        SocketChannel socketChannel1 = socketChannel.accept();
        // 循环读取
        while (true) {
            int byteRead = 0;
            while (true) {
                // 会一个一个装到buffer数组中，这里最多只会读 8 个，因为 byteBuffers 只能装 8 个byte 5 + 3
                long read = socketChannel1.read(byteBuffers);
                byteRead += read; // 累计读取的字节数
                System.out.println("byteRead=" + byteRead);
                // 使用流打印,查看当前 buffer的position和limit
                Arrays.asList(byteBuffers)
                        .stream()
                        .map(buffer -> "posiiton="+ buffer.position() + ", limit=" + buffer.limit())
                        .forEach(System.out::println);
                // 将所有的 buffer 进行 flip
                Arrays.asList(byteBuffers).forEach(Buffer::flip);

                // 将数据读出显示到客户端
                long bytewrite = 0;
                // fix https://gitee.com/yfengJ/netty-lean/issues/I3U58F
                long write = socketChannel1.write(byteBuffers);
                while(write > 0) {
                    bytewrite += write;
                    write = socketChannel1.write(byteBuffers);
                }
                // 将所有的 buffer 进行clear
                Arrays.asList(byteBuffers).forEach(Buffer::clear);
                System.out.println("byteread = " + byteRead + "bytewrite = " + bytewrite);
                break;
            }
        }

    }
}
